package com.zhyt.intelligentpipeline.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

/**
 * 管道裂纹评价模型
 * */

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CrackEvaluateModel {

    /*内外壁 0外， 1内**/
    private int type;

    /**
     * 管材最小抗拉强度 σ_u
     * */
    private double minTensileStrength;

    /**
     * 管材的最小屈服强度 σ_y
     * */
    private double minYieldStrength;

    /**
     * 断裂韧度  mm
     * */
    private double fractureToughness;

    /**
     * 弹性模量   MPa
     * */
    private double elasticModulus;
    /**
     * 管道壁厚  t
     * */
    private double pipeWallThickness;

    /**
     * 管道内半径 R
     * */
    private double pipeInnerRadius;

    /**
     * 管道外半径 R_0
     * */
    private double pipeOutRadius;


    /**
     * 裂纹深度  a
     * */
    private double crackDepth;


    /**
     * 缺陷半长  c
     * */
    private double defectHalfLength;

    /**
     * 管道运行压力 p
     * */
    private double pipelineOperatingPressure;

    /**
     * 裂纹中心处与裂纹前缘点的角度     θ
     * */
    private double centerAndCrackAngle;


    /**
     * 裂纹倾斜角度  φ（0^°≤φ≤90^°）
     * */
    private double crackInclinationAngle;


    /**
     * 泊松比，无量纲。（0.3）v
     * */
    private double poissonRatio;

    /*已检验**/
    public static double getF1(CrackEvaluateModel crackEvaluateModel){
        double a_c = crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getDefectHalfLength();
        double a_div_t = crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getPipeWallThickness();
        double M_1 = 1.13 - 0.09 * a_c;
        double M_2 = -0.54 + (0.89 / (0.2 + a_c));
        double M_3 = 0.5 - 1 /(0.65 + a_c) + 14 * Math.pow((1 - a_c),24);
        double g_sita = 1 + (0.1 + 0.35 * Math.pow(a_div_t ,2)) * (1- Math.sin(Math.toRadians(crackEvaluateModel.getCenterAndCrackAngle())));
        double f_sita = Math.pow(
                Math.pow(
                        Math.sin(
                                Math.toRadians(crackEvaluateModel.getCenterAndCrackAngle())),2
                                ) +
                        Math.pow(a_c,2) *
                        Math.pow(
                                Math.cos(Math.toRadians(crackEvaluateModel.getCenterAndCrackAngle())),
                                2)
                ,0.25);
        double part1 = 0.97 *  (M_1 + M_2 * Math.pow(a_div_t,2)  + M_3 * Math.pow(a_div_t,4));
        double h = 0;
        double R_add_R = Math.pow(crackEvaluateModel.getPipeOutRadius(), 2) + Math.pow(crackEvaluateModel.getPipeInnerRadius(),2);
        double R_sub_R = Math.pow(crackEvaluateModel.getPipeOutRadius(), 2) - Math.pow(crackEvaluateModel.getPipeInnerRadius(),2);

        double t_div_R = crackEvaluateModel.getPipeWallThickness() /  crackEvaluateModel.getPipeInnerRadius();
        if(crackEvaluateModel.getType() == 0){
            h = ((R_add_R / R_sub_R) - 1 + 0.5 * Math.sqrt(a_div_t)) * t_div_R;
        }else {
            h = ((R_add_R / R_sub_R) + 1 - 0.5 * Math.sqrt(a_div_t)) * t_div_R;
        }
        double part2 = g_sita * f_sita * h;

        return  part1 * part2;
    }

    /**已检验*/
    public static double getE(CrackEvaluateModel crackEvaluateModel){
        double a_c = crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getDefectHalfLength();
        double part1 = 1 + 1.464 * Math.pow(a_c,1.65);
        return   Math.pow(part1,0.5);
    }
    /**
     * 应力强度因子K_I 已检验
     *
     *
     * */
    public static double getStressIntensityFactor(CrackEvaluateModel crackEvaluateModel){
        double W_w = 7.616 *0.001 - 2.137 * 0.001 * crackEvaluateModel.getCrackInclinationAngle() +
                4.174 * 0.0001 *
                        Math.pow(crackEvaluateModel.getCrackInclinationAngle(),2)
                - 3.008 * 0.000001 * Math.pow(crackEvaluateModel.getCrackInclinationAngle(),3);
        double part1 = crackEvaluateModel.getPipelineOperatingPressure() * crackEvaluateModel.getPipeInnerRadius() *
                Math.sqrt(Math.PI * crackEvaluateModel.getCrackDepth());
        double part2 = crackEvaluateModel.getPipeWallThickness() * getE(crackEvaluateModel);
        double part3 = getF1(crackEvaluateModel) * W_w;

        return (part1 / part2) * part3;
    }

    /**
     * 评估截至曲线 已检验
     *
     * */
    public static double getCutOffLineOfEvaluationCurve(CrackEvaluateModel crackEvaluateModel){
        double part1 = crackEvaluateModel.getMinTensileStrength() + crackEvaluateModel.getMinYieldStrength();
        double part2 = 2 * crackEvaluateModel.getMinYieldStrength();
        return part1 / part2;
    }

    /**
     * 获取失效评估点得值
     * 公式
     * F(L_r) = (1 - 0.14 L^2_r)[0.3 + 0.7 exp (-0.65L^6_r)]
     * 计算完成后，评价点应显示在图形中，例如上面的那两个图，
     * 当评估点坐标位于失效评定曲线临界线内（左下方）时，表示裂纹处于安全状态，能维持正常运行，需监测使用
     * 反之，当评估点坐标位于失效评定曲线外（右上方）时，则表示裂纹处于不安全状态，需立即修复。
     * */
    public static double getStandard(CrackEvaluateModel crackEvaluateModel){
        double part1 = (1 - 0.14 * Math.pow(CrackEvaluateModel.getLoadRatio(crackEvaluateModel),2));
        double part2 = 0.3 + 0.7 * Math.exp(-0.65 * Math.pow(CrackEvaluateModel.getLoadRatio(crackEvaluateModel),6));
        return  part1 * part2;
    }

    /**
     * 获取管道的断裂韧性 已检验
     * K_IC=√(1.5σ_y δ_c E/(1-v^2 ) )
     *
     * */
    public static double getFractureToughness(CrackEvaluateModel crackEvaluateModel){
        return Math.sqrt(
                (
                        1.5 * crackEvaluateModel.getMinYieldStrength() * crackEvaluateModel.getFractureToughness() *
                                crackEvaluateModel.getElasticModulus()
                ) /
                (
                        1 - Math.pow(crackEvaluateModel.getPoissonRatio(),2)
                )
        );
    }

    /**
    *韧性比 已检验
    *
    * **/
    public static double getToughnessRatio(CrackEvaluateModel crackEvaluateModel){
        double part1 = CrackEvaluateModel.getStressIntensityFactor(crackEvaluateModel);
        double part2 = CrackEvaluateModel.getFractureToughness(crackEvaluateModel);
        return part1 / part2;
    }

    /**
     * 管道载荷比 已检验
     * 本项目可采用的SY/T6477-2017《含缺陷油气输送管道剩余强度评价方法》中的计算方法计算管道载荷比L_r，公式如下：
     * L_r=σ_ref/σ_y
     * */
    public static double getLoadRatio(CrackEvaluateModel crackEvaluateModel){
        return CrackEvaluateModel.getReferenceStress(crackEvaluateModel) / crackEvaluateModel.getMinYieldStrength();
    }

    /**
     * 获取参比应力 已检验
     * 公式
     * σ_ref=(gP_b+{(gP_b )^2+9[M_s×P_m×(1-α)^2 ]^2 }^0.5)/(3(1-α)^2 )
     *      其中
     *      α=(a/t)/(1+t/c)
     *      g=1-20(a/2c)^0.75 α^3
     *      M_s=1/(1-a/t+a/t (λ_a/M_t ) )
     *      λ_a=1.818c/√Ra
     *      M_t=(1+0.4845〖λ_a〗^2 )^0.5
     *      P_m=PR/t
     *      P_b=(P〖R_o〗^2)/(〖R_o〗^2-R^2 ) [t/R-3/2 (t/R)^2+9/5 (t/R)^3 ]
     * */
    public static double getReferenceStress(CrackEvaluateModel crackEvaluateModel){
        double alpha = (crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getPipeWallThickness()) /
                ( 1 + crackEvaluateModel.getPipeWallThickness() / crackEvaluateModel.getDefectHalfLength());

        double g = 1 - 20 * Math.pow(
                (
                        crackEvaluateModel.getCrackDepth() / (2 * crackEvaluateModel.getDefectHalfLength())
                ), 0.75) * Math.pow(alpha,3);

        double lambda_a = (1.818 * crackEvaluateModel.getDefectHalfLength()) /
                Math.sqrt(crackEvaluateModel.getPipeInnerRadius() * crackEvaluateModel.getCrackDepth()
                );

        double M_t = Math.pow(1 + 0.4845 * Math.pow(lambda_a,2),0.5);

        double  M_s = 1 / (
                        1 - (crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getPipeWallThickness()) +
                        (crackEvaluateModel.getCrackDepth() / crackEvaluateModel.getPipeWallThickness()) * (lambda_a / M_t)
                    );

        double P_m =( crackEvaluateModel.getPipelineOperatingPressure() * crackEvaluateModel.getPipeInnerRadius()) /
                crackEvaluateModel.getPipeWallThickness();

        double P_b  = (
                (crackEvaluateModel.getPipelineOperatingPressure() * Math.pow(crackEvaluateModel.getPipeOutRadius(),2)) /
                (
                        Math.pow(crackEvaluateModel.getPipeOutRadius(),2) - Math.pow(crackEvaluateModel.getPipeInnerRadius(),2))
        )
                *

                (
                        (crackEvaluateModel.getPipeWallThickness() / crackEvaluateModel.getPipeInnerRadius()) -
                        1.5 * Math.pow(crackEvaluateModel.getPipeWallThickness() / crackEvaluateModel.getPipeInnerRadius(),2) +
                        (1.8 * Math.pow( crackEvaluateModel.getPipeWallThickness() / crackEvaluateModel.getPipeInnerRadius(),3)));

        double sigma_ref = (( g * P_b)  + Math.pow(
                Math.pow(g * P_b,2) + 9 * Math.pow(M_s * P_m  * Math.pow(1- alpha,2),2),0.5)
        ) /
                ( 3 * Math.pow(1- alpha,2));
        return sigma_ref;
    }



}
